home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Tools 2
/
Amiga Tools 2.iso
/
grafik
/
bildanzeiger
/
seepix
/
source.lha
/
SeePix.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-11-27
|
19KB
|
718 lines
/**SeePix.c**************************************************************
* *
* SeePix -- by Hank Schafer *
* *
* SeePix is an IFF Picture Viewer. It works with Lo-Res, *
* Med-Res, Hi-Res, HAM, and EHB formats. I'm working on support *
* for X-Specs, and Anim5 formats. *
* *
* SeePix is based on a program by Olaf Barthel, called *
* 'LoadImage'. As released, LoadImage had a couple of bugs. *
* The Amiga-Key alternatives to menu use didn't all work. That's *
* been fixed. There were two separate print functions in LoadImage *
* which behaved exactly the same. The redundancy was eliminated. *
* LoadImage used the Topaz ROMFONT, and made no allowances for a *
* different system default font (under 2.04). I added a built-in *
* font. I've reworked the code considerably from the original *
* release, to allow for optimizations based on time and space. *
* *
* SeePix features a palette tool which allows "tweaking" of colors *
* prior to printing, allowing you to modify the color printout to *
* more closely resemble the original graphics (Blue is Blue, not *
* Purple). SeePix can be Iconified. SeePix features an ARP *
* interface. SeePix now uses the PathMaster File Selector. *
* *
************************************************************************
* *
* SeePix Copyright © 1992 by Hank Schafer; all rights reserved. *
* *
* This program is free software; you can redistribute it and/or *
* modify it under the terms of the GNU General Public License as *
* published by the Free Software Foundation, either version 1, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
* General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to: *
* Free Software Foundation, Inc. *
* 675 Massachusetts Ave. *
* Cambridge MA 02139, USA *
* *
**************** Special Function Copyright Notices ********************
* *
****LoadImage Copyright Notice: *
* *
* LoadImage is © Copyright 1988, 1989, 1990 by MXM, all rights *
* reserved, written by Olaf Barthel. No guarantees of any kind are *
* made that this program is 100% reliable. Use this program on *
* your own risk! *
* *
****Iconify Copyright Notice: *
* *
* Copyright 1987 by Leo L. Schwab. *
* Permission is hereby granted for use in any and all programs, *
* both Public Domain and commercial in nature, provided this *
* Copyright notice is left intact. *
* *
****ColorWindow (Palette) Copyright Notice: *
* *
* ColorWindow Routine -- Color Window Routines *
* from Book 1 of the Amiga Programmers' Suite by RJ Mical *
* *
* Copyright (C) 1986, 1987, Robert J. Mical *
* All Rights Reserved. *
* *
****PathMaster Copyright Notice: *
* *
* -------------------------------------------------------------------- *
* Copyright © 1989 Justin V. McCormick. All Rights Reserved. *
* -------------------------------------------------------------------- *
* *
* The PathMaster name is a trademark of Justin V. McCormick. *
* *
* PathMaster File Selector source and documentation written by: *
* *
* Justin V. McCormick. *
* Copyright © 1989 by Justin V. McCormick. *
* All Rights Reserved. *
* *
* -------------------------------------------------------------------- *
************************************************************************
* *
* Hope this is something you can use and enjoy. *
* *
************************************************************************/
/*
* SeePix()
*
* Will load and display an image file.
*/
/* All the external stuff */
extern struct Screen *Screen;
extern struct Window *Window;
extern struct BitMap ScreenMap;
extern struct BitMap TinyBitMap;
extern struct NewScreen NewScreen;
BitMapHeader InfoHeader;
CRange CycleRange[6];
#ifdef FANCYMENU
extern UWORD PrefColors[];
extern struct Preferences StandardPrefs;
#endif /* FANCYMENU */
extern struct MenuItem MenuItem[13];
extern struct Menu Menu;
extern struct Border ReqBrd[];
extern struct Gadget ReqGad;
extern struct Requester Req;
extern struct IntuiText ReqIntTxt[];
extern struct NewWindow NewWindow;
extern struct IntuitionBase *IntuitionBase;
extern struct GfxBase *GfxBase;
extern struct ExecBase *SysBase;
LONG ViewModes;
/*
* Get down to bizness...
*/
LONG
SeePix(char *FileName, UBYTE ForceScroll, UBYTE ForceLace, UBYTE CycleOnStartup, UBYTE LastOne)
{
WORD MaxOffsetX, MaxOffsetY; /* Some scrolling stuff. */
volatile WORD StartOffsetX, StartOffsetY;
WORD Width, Height; /* Size of the ViewPort */
WORD JumpY = 1, JumpX = 1; /* Scrolljump steps */
UBYTE WeAreScrolling = FALSE;
UBYTE RemakeTheView;
UWORD MenuNum;
struct MenuItem *Item;
UBYTE IsMouse; /* Scrollmode. */
UBYTE ChangedColors = FALSE;
UBYTE IsTiny = FALSE; /* Image smaller than screen? */
LONG TinyX, TinyY; /* Image offsets for tiny bitmap. */
struct IntuiMessage *Message;
ULONG Class;
UWORD Code;
WORD i; /* Loop counters. */
volatile UBYTE *RightMouse = (UBYTE *) 0xDFF016;
char RealName[108];
GRName(FileName, RealName);
/* Is it the last picture? */
if (LastOne)
MenuItem[11].Flags &= ~ITEMENABLED;
else
MenuItem[11].Flags |= ITEMENABLED;
/* Try to load the header. */
if ((ViewModes = LoadHead(FileName, &InfoHeader)) == -1)
return (ERR_NOIFF);
/* Are there any colors out there? */
if (!(ColorNumber = LoadCMAP(FileName, Colors, 32, &InfoHeader)))
return (ERR_NOCOLMAP);
/* Take care of the size of the ViewPort. */
Width = InfoHeader.pageWidth;
Height = InfoHeader.pageHeight;
/* Forced scrolling? */
if (ForceScroll)
ViewModes &= ~(HIRES | LACE);
/* Forced interlaced display mode? */
if (ForceLace)
ViewModes |= LACE;
/* Take care of exotic screen sizes. */
if (InfoHeader.h > Height)
Height = InfoHeader.h;
if (InfoHeader.w > Width)
Width = InfoHeader.w;
/* Hires or lores? */
if (ViewModes & HIRES) {
Width = 640;
JumpX = 2;
} else
Width = 320;
/*
* Interlaced or not? This may get funny since it is possible to scroll
* the image in steps of one pixel. In doing so one copper list (either
* shortframe or longframe) is ignored and only half of the image is
* displayed correctly. To avoid this the scroll jump is set to two
* pixels.
*/
if (ViewModes & LACE)
JumpY = 2;
if (Height > GfxBase->NormalDisplayRows * JumpY)
Height = GfxBase->NormalDisplayRows * JumpY;
/* Adjust the information. */
NewScreen.Width = Width;
NewScreen.Height = Height;
NewScreen.Depth = InfoHeader.nPlanes;
NewScreen.ViewModes = ViewModes;
/* And don't forget the window. */
NewWindow.Width = Width;
NewWindow.Height = Height;
/* Anything wrong with the picture? */
if (InfoHeader.w < InfoHeader.pageWidth || InfoHeader.h < InfoHeader.pageHeight) {
if (!ITBMap())
return (ERR_NOMEM);
IsTiny = TRUE;
} else {
/* Initialize the bitmap for future use. */
InitBitMap(&ScreenMap, InfoHeader.nPlanes, InfoHeader.w, InfoHeader.h);
/* Try to steal some memory for the bitplanes. */
for (i = 0; i < InfoHeader.nPlanes; i++) {
if (!(ScreenMap.Planes[i] = (PLANEPTR) AllocRaster(InfoHeader.w, InfoHeader.h)))
return (ERR_NOMEM);
IsTiny = FALSE;
}
}
/* Open the screen. */
if (!(Screen = (struct Screen *) OpenScreen(&NewScreen)))
return (ERR_NOMEM);
/* Hide the title bar and prepare the window. */
ShowTitle(Screen, FALSE);
NewWindow.Screen = Screen;
/* Try to open the window. */
if (!(Window = (struct Window *) OpenWindow(&NewWindow)))
return (ERR_NOMEM);
SetSnooze(Window);
SetWindowTitles(Window, (CPTR) - 1, (CPTR) RealName);
#ifdef FANCYMENU
/* Set up the alternate colour palette. */
for (i = 0; i < 32; i++) {
PrefColors[i] = Colors[i];
if (i >= (1 << NewScreen.Depth))
PrefColors[i] = Colors[i] = GetRGB4(Screen->ViewPort.ColorMap, i);
}
PrefColors[0] = StandardPrefs.color0;
PrefColors[1] = StandardPrefs.color1;
PrefColors[2] = StandardPrefs.color2;
PrefColors[3] = StandardPrefs.color3;
#endif /* FANCYMENU */
/* Load the colors. */
LoadRGB4(&Screen->ViewPort, Colors, ColorNumber);
/* Just in case we will have to restore it. */
StartOffsetX = Screen->ViewPort.RasInfo->RxOffset;
StartOffsetY = Screen->ViewPort.RasInfo->RyOffset;
/*
* Play it safe --- keep the maximum scroll offset in reasonable
* dimensions.
*/
if ((MaxOffsetX = InfoHeader.w - Width) < 0)
MaxOffsetX = 0;
if ((MaxOffsetY = InfoHeader.h - Height) < 0)
MaxOffsetY = 0;
/* Absolute maximum limit. */
MaxOffsetX += StartOffsetX;
MaxOffsetY += StartOffsetY;
/* "Here comes the sun..." */
if (IsTiny) {
if (!LoadRast(FileName, TinyBitMap.Planes, &InfoHeader))
return (ERR_DOS);
} else {
if (!LoadRast(FileName, ScreenMap.Planes, &InfoHeader))
return (ERR_DOS);
}
/* Do we allow color cycling? */
if (LoadCycleRange(FileName, CycleRange, 6))
InitCycle(&Screen->ViewPort, Colors, ColorNumber, CycleRange, 6);
/* Install the menu and the pointer. */
SetMenuStrip(Window, &Menu);
SetPoint(Window);
/* And - if necessary - print the tiny image. */
if (IsTiny) {
if (InfoHeader.x + InfoHeader.w <= Screen->Width)
TinyX = InfoHeader.x;
else
TinyX = (NewScreen.Width - InfoHeader.w) >> 1;
if (InfoHeader.y + InfoHeader.h <= Screen->Height)
TinyY = InfoHeader.y;
else
TinyY = (NewScreen.Height - InfoHeader.h) >> 1;
BltBitMap(&TinyBitMap, 0, 0, Screen->RastPort.BitMap, TinyX, TinyY, InfoHeader.w, InfoHeader.h, 0xC0, 0xFF, NULL);
}
/* Paint the screen black (for the effect). */
if (!(ViewModes & HAM))
LoadRGB4(&Screen->ViewPort, BlackIsBlack, ColorNumber);
/* Bring the screen to the front. */
ScreenToFront(Screen);
ActivateWindow(Window);
FreeSprite(0);
/* Fade the colors in. */
if (!(ViewModes & HAM))
FadeTo(&Screen->ViewPort, NULL, Colors, ColorNumber, 0, 0);
/* Allow the menu to be selected. */
Window->Flags &= ~RMBTRAP;
/* If we are to cycle... */
if (CycleOnStartup)
ToggleCycle();
FOREVER
{
/* Let's be nice and wait for reactions. */
WaitPort(Window->UserPort);
/* Message the userport. */
if (Message = (struct IntuiMessage *) GetMsg(Window->UserPort)) {
Class = Message->Class;
Code = Message->Code;
/*
* If the user presses the menu button the menu appears. There is
* nothing wrong with this, but it might be possible that the
* user does not see the menu because of the raster offset. So we
* reposition the ViewPort before Intuition renders the menu bar.
* To keep the menu visible we adjust the colors if the right
* mouse button is pressed. This is done because of the fact that
* the keyboard shortcuts generate the same MENUVERIFY event. If
* there is anyone who doesn't like it this way he can try to
* test the keyboard matrix by tickling the hardware. I have
* chosen the easier way.
*/
if (Class == MENUVERIFY && !(*RightMouse & 4)) {
if (WasCycling = IsCycle())
ToggleCycle();
#ifdef FANCYMENU
LoadRGB4(&Screen->ViewPort, PrefColors, 32);
ChangedColors = TRUE;
#endif /* FANCYMENU */
/* Reset the offsets. */
Screen->ViewPort.RasInfo->RxOffset = StartOffsetX;
Screen->ViewPort.RasInfo->RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
}
ReplyMsg(Message);
}
/*
* If the user presses the select button we'll assume that he wants
* to scroll around in the picture.
*/
if (Class == MOUSEBUTTONS && Code == SELECTDOWN) {
FreeSprite(0);
if (ChangedColors) {
LoadRGB4(&Screen->ViewPort, Colors, ColorNumber);
ChangedColors = FALSE;
if (WasCycling)
ToggleCycle();
WasCycling = FALSE;
}
WeAreScrolling = TRUE;
IsMouse = TRUE;
}
/*
* User pressed the cursor keys and wants to scroll around in the
* picture.
*/
if (Class == RAWKEY && (Code & ~IECODE_UP_PREFIX) >= CURSORUP && (Code & ~IECODE_UP_PREFIX) <= CURSORLEFT) {
FreeSprite(0);
WeAreScrolling = TRUE;
IsMouse = FALSE;
}
/*
* User didn't like the menu shortcut and pressed the Tab key (is he
* a DPaint fanatic?).
*/
if (Class == RAWKEY && Code == 0x42) {
FreeSprite(0);
ToggleCycle();
}
/* The user picked a menu item. */
if (Class == MENUPICK) {
if (ChangedColors) {
LoadRGB4(&Screen->ViewPort, Colors, ColorNumber);
if (WasCycling)
ToggleCycle();
ChangedColors = FALSE;
WasCycling = FALSE;
}
MenuNum = Code;
/* Until the last event is traced. */
while (MenuNum != MENUNULL) {
if (MENUNUM(MenuNum) == 0) {
switch (ITEMNUM(MenuNum)) {
/* About... */
case 0:
if (WasCycling = IsCycle())
ToggleCycle();
#ifdef FANCYMENU
LoadRGB4(&Screen->ViewPort, PrefColors, 32);
#endif /* FANCYMENU */
Screen->ViewPort.RasInfo->RxOffset = StartOffsetX;
Screen->ViewPort.RasInfo->RyOffset = StartOffsetY;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
InitRequester(&Req);
Req.Width = 300;
Req.Height = 175;
Req.LeftEdge = (Window->Width - Req.Width) / 2;
Req.TopEdge = (Window->Height - Req.Height) / 2;
Req.BackFill = 1;
Req.Flags = NOISYREQ | SIMPLEREQ;
Req.ReqGadget = &ReqGad;
Req.ReqBorder = &ReqBrd[2];
Req.ReqText = &ReqIntTxt[1];
if (Request(&Req, Window)) {
FOREVER
{
WaitPort(Window->UserPort);
while (Message = (struct IntuiMessage *) GetMsg(Window->UserPort)) {
Class = Message->Class;
ReplyMsg(Message);
if (Class == GADGETUP) {
EndRequest(&Req, Window);
goto EndReq;
}
}
}
}
EndReq:
SetPoint(Window);
LoadRGB4(&Screen->ViewPort, Colors, ColorNumber);
if (WasCycling)
ToggleCycle();
FreeSprite(0);
break;
/* Toggle the presence of the screen title. */
case 2:
FreeSprite(0);
if (Screen->Flags & SHOWTITLE)
ShowTitle(Screen, FALSE);
else
ShowTitle(Screen, TRUE);
break;
/* Toggle cycling. */
case 3:
FreeSprite(0);
ToggleCycle();
break;
/* Print screen */
case 5:
if (IsCycle())
ToggleCycle();
WasCycling = FALSE;
/* Remake the copper list. */
MakeScreen(Screen);
RethinkDisplay();
PrintPix();
break;
/* Modify colors and start the presses */
case 7:
if (IsCycle())
ToggleCycle();
WasCycling = FALSE;
DoCWind(Screen, 10, 10, 1, TRUE);
break;
/* Iconify */
case 9:
if (IsCycle())
ToggleCycle();
WasCycling = FALSE;
ScreenToBack(Screen);
CloseDisp();
Iconize();
return (0);
/* Next Picture */
case 11:
if (IsCycle())
ToggleCycle();
WasCycling = FALSE;
if (!(ViewModes & HAM))
FadeTo(&Screen->ViewPort, Colors, NULL, ColorNumber, 0, 0);
ScreenToBack(Screen);
CloseDisp();
return (0);
/* Quit SeePix. */
case 12:
SPQuit();
}
}
/* See if there is another menu item around. */
Item = (struct MenuItem *) ItemAddress(&Menu, MenuNum);
MenuNum = Item->NextSelect;
}
}
/* No chance to scroll anywhere, so we'll block it. */
if (MaxOffsetX == StartOffsetX && MaxOffsetY == StartOffsetY)
WeAreScrolling = FALSE;
/*
* This loop will run until the select button or the cursor key is
* released.
*/
while (WeAreScrolling) {
if (Message = (struct IntuiMessage *) GetMsg(Window->UserPort)) {
Class = Message->Class;
Code = Message->Code;
ReplyMsg(Message);
}
/* User doesn't want to scroll anymore? */
if (Code & IECODE_UP_PREFIX) {
FreeSprite(0);
WeAreScrolling = FALSE;
}
/* Nothing happened. */
RemakeTheView = FALSE;
/* Left border, scroll left. */
if (((Window->MouseX == 0 && IsMouse) || (Code == CURSORLEFT && !IsMouse)) && (Screen->ViewPort.RasInfo->RxOffset - JumpX >= StartOffsetX)) {
Screen->ViewPort.RasInfo->RxOffset -= JumpX;
RemakeTheView = TRUE;
}
/* Top border, scroll up. */
if (((Window->MouseY == 0 && IsMouse) || (Code == CURSORUP && !IsMouse)) && (Screen->ViewPort.RasInfo->RyOffset - JumpY >= StartOffsetY)) {
Screen->ViewPort.RasInfo->RyOffset -= JumpY;
RemakeTheView = TRUE;
}
/* Right border, scroll right. */
if (((Window->MouseX == Window->Width - 1 && IsMouse) || (Code == CURSORRIGHT && !IsMouse)) && (Screen->ViewPort.RasInfo->RxOffset + JumpX <= MaxOffsetX)) {
Screen->ViewPort.RasInfo->RxOffset += JumpX;
RemakeTheView = TRUE;
}
/* Bottom border, scroll down. */
if (((Window->MouseY == Window->Height - 1 && IsMouse) || (Code == CURSORDOWN && !IsMouse)) && (Screen->ViewPort.RasInfo->RyOffset + JumpY <= MaxOffsetY)) {
Screen->ViewPort.RasInfo->RyOffset += JumpY;
RemakeTheView = TRUE;
}
/* Are we to scroll the ViewPort? */
if (RemakeTheView) {
MakeScreen(Screen);
RethinkDisplay();
}
}
}
}